from datetime import datetime, timedelta
from app import db
from sqlalchemy.dialects.postgresql import JSON
import json

class User(db.Model):
    """用户模型"""
    __tablename__ = 'users'
    
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True, nullable=False)
    email = db.Column(db.String(120), unique=True, nullable=False)
    password_hash = db.Column(db.String(128), nullable=False)
    role = db.Column(db.String(20), nullable=False)  # patient, doctor, admin
    phone = db.Column(db.String(20))
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    is_active = db.Column(db.Boolean, default=True)
    
    # 关联关系
    appointments = db.relationship('Appointment', backref='patient', lazy='dynamic')
    doctor_schedules = db.relationship('DoctorSchedule', backref='doctor', lazy='dynamic')

class Department(db.Model):
    """科室模型"""
    __tablename__ = 'departments'
    
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100), nullable=False)
    description = db.Column(db.Text)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    
    # 关联关系
    resources = db.relationship('Resource', backref='department', lazy='dynamic')
    appointments = db.relationship('Appointment', backref='department', lazy='dynamic')

class Resource(db.Model):
    """资源模型（床位、手术室、检查设备等）"""
    __tablename__ = 'resources'
    
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100), nullable=False)
    resource_type = db.Column(db.String(50), nullable=False)  # bed, operating_room, equipment
    department_id = db.Column(db.Integer, db.ForeignKey('departments.id'), nullable=False)
    capacity = db.Column(db.Integer, default=1)
    status = db.Column(db.String(20), default='available')  # available, occupied, maintenance
    location = db.Column(db.String(200))
    specifications = db.Column(JSON)  # 设备规格信息
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    
    # 关联关系
    schedules = db.relationship('ResourceSchedule', backref='resource', lazy='dynamic')

class Appointment(db.Model):
    """预约模型"""
    __tablename__ = 'appointments'
    
    id = db.Column(db.Integer, primary_key=True)
    patient_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
    department_id = db.Column(db.Integer, db.ForeignKey('departments.id'), nullable=False)
    appointment_type = db.Column(db.String(50), nullable=False)  # consultation, surgery, examination
    scheduled_time = db.Column(db.DateTime, nullable=False)
    duration = db.Column(db.Integer, default=30)  # 分钟
    status = db.Column(db.String(20), default='pending')  # pending, confirmed, completed, cancelled
    priority = db.Column(db.Integer, default=1)  # 1-5，5为最高优先级
    notes = db.Column(db.Text)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
    
    # 关联关系
    resource_assignments = db.relationship('ResourceAssignment', backref='appointment', lazy='dynamic')

class ResourceAssignment(db.Model):
    """资源分配模型"""
    __tablename__ = 'resource_assignments'
    
    id = db.Column(db.Integer, primary_key=True)
    appointment_id = db.Column(db.Integer, db.ForeignKey('appointments.id'), nullable=False)
    resource_id = db.Column(db.Integer, db.ForeignKey('resources.id'), nullable=False)
    start_time = db.Column(db.DateTime, nullable=False)
    end_time = db.Column(db.DateTime, nullable=False)
    status = db.Column(db.String(20), default='assigned')  # assigned, confirmed, completed
    created_at = db.Column(db.DateTime, default=datetime.utcnow)

class ResourceSchedule(db.Model):
    """资源排程模型"""
    __tablename__ = 'resource_schedules'
    
    id = db.Column(db.Integer, primary_key=True)
    resource_id = db.Column(db.Integer, db.ForeignKey('resources.id'), nullable=False)
    start_time = db.Column(db.DateTime, nullable=False)
    end_time = db.Column(db.DateTime, nullable=False)
    status = db.Column(db.String(20), nullable=False)  # available, occupied, maintenance
    appointment_id = db.Column(db.Integer, db.ForeignKey('appointments.id'))
    created_at = db.Column(db.DateTime, default=datetime.utcnow)

class DoctorSchedule(db.Model):
    """医生排班模型"""
    __tablename__ = 'doctor_schedules'
    
    id = db.Column(db.Integer, primary_key=True)
    doctor_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
    start_time = db.Column(db.DateTime, nullable=False)
    end_time = db.Column(db.DateTime, nullable=False)
    department_id = db.Column(db.Integer, db.ForeignKey('departments.id'), nullable=False)
    max_patients = db.Column(db.Integer, default=20)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)

class SchedulingResult(db.Model):
    """调度结果模型"""
    __tablename__ = 'scheduling_results'
    
    id = db.Column(db.Integer, primary_key=True)
    algorithm_used = db.Column(db.String(50), nullable=False)  # NSGA2, WOA, DQN
    optimization_objectives = db.Column(JSON)  # 优化目标结果
    resource_utilization = db.Column(db.Float)  # 资源利用率
    patient_wait_time = db.Column(db.Float)  # 患者等待时间
    fairness_score = db.Column(db.Float)  # 公平性评分
    execution_time = db.Column(db.Float)  # 执行时间（秒）
    created_at = db.Column(db.DateTime, default=datetime.utcnow)

class Notification(db.Model):
    """通知模型"""
    __tablename__ = 'notifications'
    
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
    title = db.Column(db.String(200), nullable=False)
    content = db.Column(db.Text, nullable=False)
    notification_type = db.Column(db.String(50), nullable=False)  # appointment, schedule, system
    is_read = db.Column(db.Boolean, default=False)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)

class SystemMetrics(db.Model):
    """系统指标模型"""
    __tablename__ = 'system_metrics'
    
    id = db.Column(db.Integer, primary_key=True)
    metric_name = db.Column(db.String(100), nullable=False)
    metric_value = db.Column(db.Float, nullable=False)
    metric_unit = db.Column(db.String(20))
    timestamp = db.Column(db.DateTime, default=datetime.utcnow)
    metadata = db.Column(JSON)  # 额外元数据
